R has some powerful graphing functionality. If you end up doing a lot of graphing then you’ll probably want to use the ggplot2 package, which unifies and simplifies the process. But you can achieve a lot fairly easily using base R directly. Plus, it’s good to understand what’s going on behind the scenes of a package like ggpolot2.
You can see some demonstrations of graphing with base R using the demo function:
demo(graphics)
##
##
## demo(graphics)
## ---- ~~~~~~~~
##
## > # Copyright (C) 1997-2009 The R Core Team
## >
## > require(datasets)
##
## > require(grDevices); require(graphics)
##
## > ## Here is some code which illustrates some of the differences between
## > ## R and S graphics capabilities. Note that colors are generally specified
## > ## by a character string name (taken from the X11 rgb.txt file) and that line
## > ## textures are given similarly. The parameter "bg" sets the background
## > ## parameter for the plot and there is also an "fg" parameter which sets
## > ## the foreground color.
## >
## >
## > x <- stats::rnorm(50)
##
## > opar <- par(bg = "white")
##
## > plot(x, ann = FALSE, type = "n")
##
## > abline(h = 0, col = gray(.90))
##
## > lines(x, col = "green4", lty = "dotted")
##
## > points(x, bg = "limegreen", pch = 21)
##
## > title(main = "Simple Use of Color In a Plot",
## + xlab = "Just a Whisper of a Label",
## + col.main = "blue", col.lab = gray(.8),
## + cex.main = 1.2, cex.lab = 1.0, font.main = 4, font.lab = 3)
##
## > ## A little color wheel. This code just plots equally spaced hues in
## > ## a pie chart. If you have a cheap SVGA monitor (like me) you will
## > ## probably find that numerically equispaced does not mean visually
## > ## equispaced. On my display at home, these colors tend to cluster at
## > ## the RGB primaries. On the other hand on the SGI Indy at work the
## > ## effect is near perfect.
## >
## > par(bg = "gray")
##
## > pie(rep(1,24), col = rainbow(24), radius = 0.9)
##
## > title(main = "A Sample Color Wheel", cex.main = 1.4, font.main = 3)
##
## > title(xlab = "(Use this as a test of monitor linearity)",
## + cex.lab = 0.8, font.lab = 3)
##
## > ## We have already confessed to having these. This is just showing off X11
## > ## color names (and the example (from the postscript manual) is pretty "cute".
## >
## > pie.sales <- c(0.12, 0.3, 0.26, 0.16, 0.04, 0.12)
##
## > names(pie.sales) <- c("Blueberry", "Cherry",
## + "Apple", "Boston Cream", "Other", "Vanilla Cream")
##
## > pie(pie.sales,
## + col = c("purple","violetred1","green3","cornsilk","cyan","white"))
##
## > title(main = "January Pie Sales", cex.main = 1.8, font.main = 1)
##
## > title(xlab = "(Don't try this at home kids)", cex.lab = 0.8, font.lab = 3)
##
## > ## Boxplots: I couldn't resist the capability for filling the "box".
## > ## The use of color seems like a useful addition, it focuses attention
## > ## on the central bulk of the data.
## >
## > par(bg="cornsilk")
##
## > n <- 10
##
## > g <- gl(n, 100, n*100)
##
## > x <- rnorm(n*100) + sqrt(as.numeric(g))
##
## > boxplot(split(x,g), col="lavender", notch=TRUE)
##
## > title(main="Notched Boxplots", xlab="Group", font.main=4, font.lab=1)
##
## > ## An example showing how to fill between curves.
## >
## > par(bg="white")
##
## > n <- 100
##
## > x <- c(0,cumsum(rnorm(n)))
##
## > y <- c(0,cumsum(rnorm(n)))
##
## > xx <- c(0:n, n:0)
##
## > yy <- c(x, rev(y))
##
## > plot(xx, yy, type="n", xlab="Time", ylab="Distance")
##
## > polygon(xx, yy, col="gray")
##
## > title("Distance Between Brownian Motions")
##
## > ## Colored plot margins, axis labels and titles. You do need to be
## > ## careful with these kinds of effects. It's easy to go completely
## > ## over the top and you can end up with your lunch all over the keyboard.
## > ## On the other hand, my market research clients love it.
## >
## > x <- c(0.00, 0.40, 0.86, 0.85, 0.69, 0.48, 0.54, 1.09, 1.11, 1.73, 2.05, 2.02)
##
## > par(bg="lightgray")
##
## > plot(x, type="n", axes=FALSE, ann=FALSE)
##
## > usr <- par("usr")
##
## > rect(usr[1], usr[3], usr[2], usr[4], col="cornsilk", border="black")
##
## > lines(x, col="blue")
##
## > points(x, pch=21, bg="lightcyan", cex=1.25)
##
## > axis(2, col.axis="blue", las=1)
##
## > axis(1, at=1:12, lab=month.abb, col.axis="blue")
##
## > box()
##
## > title(main= "The Level of Interest in R", font.main=4, col.main="red")
##
## > title(xlab= "1996", col.lab="red")
##
## > ## A filled histogram, showing how to change the font used for the
## > ## main title without changing the other annotation.
## >
## > par(bg="cornsilk")
##
## > x <- rnorm(1000)
##
## > hist(x, xlim=range(-4, 4, x), col="lavender", main="")
##
## > title(main="1000 Normal Random Variates", font.main=3)
##
## > ## A scatterplot matrix
## > ## The good old Iris data (yet again)
## >
## > pairs(iris[1:4], main="Edgar Anderson's Iris Data", font.main=4, pch=19)
##
## > pairs(iris[1:4], main="Edgar Anderson's Iris Data", pch=21,
## + bg = c("red", "green3", "blue")[unclass(iris$Species)])
##
## > ## Contour plotting
## > ## This produces a topographic map of one of Auckland's many volcanic "peaks".
## >
## > x <- 10*1:nrow(volcano)
##
## > y <- 10*1:ncol(volcano)
##
## > lev <- pretty(range(volcano), 10)
##
## > par(bg = "lightcyan")
##
## > pin <- par("pin")
##
## > xdelta <- diff(range(x))
##
## > ydelta <- diff(range(y))
##
## > xscale <- pin[1]/xdelta
##
## > yscale <- pin[2]/ydelta
##
## > scale <- min(xscale, yscale)
##
## > xadd <- 0.5*(pin[1]/scale - xdelta)
##
## > yadd <- 0.5*(pin[2]/scale - ydelta)
##
## > plot(numeric(0), numeric(0),
## + xlim = range(x)+c(-1,1)*xadd, ylim = range(y)+c(-1,1)*yadd,
## + type = "n", ann = FALSE)
##
## > usr <- par("usr")
##
## > rect(usr[1], usr[3], usr[2], usr[4], col="green3")
##
## > contour(x, y, volcano, levels = lev, col="yellow", lty="solid", add=TRUE)
##
## > box()
##
## > title("A Topographic Map of Maunga Whau", font= 4)
##
## > title(xlab = "Meters North", ylab = "Meters West", font= 3)
##
## > mtext("10 Meter Contour Spacing", side=3, line=0.35, outer=FALSE,
## + at = mean(par("usr")[1:2]), cex=0.7, font=3)
##
## > ## Conditioning plots
## >
## > par(bg="cornsilk")
##
## > coplot(lat ~ long | depth, data = quakes, pch = 21, bg = "green3")
##
## > par(opar)
Or, for 3D graphing:
demo(persp)
##
##
## demo(persp)
## ---- ~~~~~
##
## > ### Demos for persp() plots -- things not in example(persp)
## > ### -------------------------
## >
## > require(datasets)
##
## > require(grDevices); require(graphics)
##
## > ## (1) The Obligatory Mathematical surface.
## > ## Rotated sinc function.
## >
## > x <- seq(-10, 10, length.out = 50)
##
## > y <- x
##
## > rotsinc <- function(x,y)
## + {
## + sinc <- function(x) { y <- sin(x)/x ; y[is.na(y)] <- 1; y }
## + 10 * sinc( sqrt(x^2+y^2) )
## + }
##
## > sinc.exp <- expression(z == Sinc(sqrt(x^2 + y^2)))
##
## > z <- outer(x, y, rotsinc)
##
## > oldpar <- par(bg = "white")
##
## > persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "lightblue")
##
## > title(sub=".")## work around persp+plotmath bug
##
## > title(main = sinc.exp)
##
## > persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "lightblue",
## + ltheta = 120, shade = 0.75, ticktype = "detailed",
## + xlab = "X", ylab = "Y", zlab = "Z")
##
## > title(sub=".")## work around persp+plotmath bug
##
## > title(main = sinc.exp)
##
## > ## (2) Visualizing a simple DEM model
## >
## > z <- 2 * volcano # Exaggerate the relief
##
## > x <- 10 * (1:nrow(z)) # 10 meter spacing (S to N)
##
## > y <- 10 * (1:ncol(z)) # 10 meter spacing (E to W)
##
## > persp(x, y, z, theta = 120, phi = 15, scale = FALSE, axes = FALSE)
##
## > ## (3) Now something more complex
## > ## We border the surface, to make it more "slice like"
## > ## and color the top and sides of the surface differently.
## >
## > z0 <- min(z) - 20
##
## > z <- rbind(z0, cbind(z0, z, z0), z0)
##
## > x <- c(min(x) - 1e-10, x, max(x) + 1e-10)
##
## > y <- c(min(y) - 1e-10, y, max(y) + 1e-10)
##
## > fill <- matrix("green3", nrow = nrow(z)-1, ncol = ncol(z)-1)
##
## > fill[ , i2 <- c(1,ncol(fill))] <- "gray"
##
## > fill[i1 <- c(1,nrow(fill)) , ] <- "gray"
##
## > par(bg = "lightblue")
##
## > persp(x, y, z, theta = 120, phi = 15, col = fill, scale = FALSE, axes = FALSE)
##
## > title(main = "Maunga Whau\nOne of 50 Volcanoes in the Auckland Region.",
## + font.main = 4)
##
## > par(bg = "slategray")
##
## > persp(x, y, z, theta = 135, phi = 30, col = fill, scale = FALSE,
## + ltheta = -120, lphi = 15, shade = 0.65, axes = FALSE)
##
## > ## Don't draw the grid lines : border = NA
## > persp(x, y, z, theta = 135, phi = 30, col = "green3", scale = FALSE,
## + ltheta = -120, shade = 0.75, border = NA, box = FALSE)
##
## > ## `color gradient in the soil' :
## > fcol <- fill ; fcol[] <- terrain.colors(nrow(fcol))
##
## > persp(x, y, z, theta = 135, phi = 30, col = fcol, scale = FALSE,
## + ltheta = -120, shade = 0.3, border = NA, box = FALSE)
##
## > ## `image like' colors on top :
## > fcol <- fill
##
## > zi <- volcano[ -1,-1] + volcano[ -1,-61] +
## + volcano[-87,-1] + volcano[-87,-61] ## / 4
##
## > fcol[-i1,-i2] <-
## + terrain.colors(20)[cut(zi,
## + stats::quantile(zi, seq(0,1, length.out = 21)),
## + include.lowest = TRUE)]
##
## > persp(x, y, 2*z, theta = 110, phi = 40, col = fcol, scale = FALSE,
## + ltheta = -120, shade = 0.4, border = NA, box = FALSE)
##
## > ## reset par():
## > par(oldpar)
What you need to know
There are five things you need to know about in order to understand graphing in R: - Graphical devices - High level graphical functions - Options and parameters - Low level graphical functions - Multi-plotting
We’ll go through each of these in the following slides.
You make graphs in R by calling graphical functions. When you call one of these functions its output gets sent to a graphical device, which is either a graphical window or a file.
The graphical devices available to you include: - A window - A pdf file - A png file - An svg file
To get a complete list you can use help(device) or
?device:
?device
When you call a graphical function the output gets sent to the current graphical device. If there are no devices open, and thus no current device, then R opens a graphical window, makes it the current device, and sends the output there.
You can open a graphical device manually:
# Open a pdf file
pdf()
# Open a png file
png()
# Open an svg file
svg()
When you open a device in this way it becomes the current device. You see which devices are open and which one is current using the dev.list and dev.cur functions. Note that each device has a number.
pdf()
pdf()
svg()
# Get a list of open devices
dev.list()
## png pdf png svg pdf pdf svg
## 2 3 4 5 6 7 8
# Get the current device
dev.cur()
## svg
## 8
You can change the active device to one of the other open devices
using dev.set, and specifying the number of the device
you’d like to make current (the dev.list function tells you
the number of each device). Note that dev.set returns the
active device.
pdf()
pdf()
svg()
dev.list()
## png pdf png svg pdf pdf svg pdf pdf svg
## 2 3 4 5 6 7 8 9 10 11
# Set the current device to device number 2
dev.set(2)
## png
## 2
You can close the active device using dev.off. R makes
the first device the active device and reports this.
pdf()
pdf()
svg()
dev.list()
## png pdf png svg pdf pdf svg pdf pdf svg pdf pdf svg
## 2 3 4 5 6 7 8 9 10 11 12 13 14
# Close the active device
dev.off()
## png
## 2
dev.list()
## png pdf png svg pdf pdf svg pdf pdf svg pdf pdf
## 2 3 4 5 6 7 8 9 10 11 12 13
You can close another device by specifying its device number. Since you are not closing the active device it remains active.
pdf()
pdf()
svg()
svg()
pdf()
pdf()
dev.list()
## png pdf png svg pdf pdf svg pdf pdf svg pdf pdf pdf pdf svg svg pdf pdf
## 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# Close device number 4
dev.off(4)
## pdf
## 19
dev.list()
## png pdf svg pdf pdf svg pdf pdf svg pdf pdf pdf pdf svg svg pdf pdf
## 2 3 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
High level graphical functions are what you use to start a new graph and plot its main features. There are many such functions - here we just consider some of the most frequently used ones.
The plot function allows you to plot a wide variety of objects and pairs of objects. Here are some of the most useful.You can try other objects and pairs of objects yourself.
For a numeric vector (integer, double) the values get plotted in order of position:
plot(iris$Petal.Width)
Note that this includes factors, since factors are integer vectors under
the hood. Although, R uses the levels of the factor to make the graph
more informative:
plot(iris$Species) # iris#Species is a factor
Other types of atomic vectors get coerced into numeric vectors, if possible.
plot(c('1','2','3')) # Character vector coerced into numeric
plot(iris$Petal.Width > 1) # Logical vector coerced into numeric
# A pair of atomic vectors If you specify a numeric vector for x and y
then R will plot them as a scatter plot:
plot(
x = iris$Petal.Width,
y = iris$Sepal.Width,
)
If x is a factor then it will make a boxplot:
plot(
x = iris$Species,
y = iris$Sepal.Width,
)
# A list R looks for elements in the list with names “x” and “y”, and
plots them:
lst <- list(x=1:10, y=2*(1:10), z=3:5)
plot(lst)
# A data frame R makes a grid of scatter plots, one for each pair of
columns in the data frame.
plot(iris)
# A function R plots the function. You can specify a range of x values
using from and to.
plot(sin, from=0, to=2*pi)
# The boxplot function You can use the boxplot function to visualise the
five number summary of a vector of numeric values: minimum value, lower
quartile, mean value, upper quartile, maximum value.
boxplot(iris$Sepal.Width)
# The hist function You can use the hist function to show a frequency
histogram of the values in a numeric vector. You can specify the number
of bins using breaks.
hist(iris$Sepal.Width, breaks=20)
If you’d rather see relative frequencies then you can add freq=FALSE.
hist(iris$Sepal.Width, breaks=20, freq=FALSE)
# The barplot function For numerical vectors. Can turn categorical into
numerical using table.
barplot(table(iris$Species))
Options: - width - beside
A clustered bar chart is an effective tool for displaying the relationship between two categorical variables. R can construct a clustered bar chart from a table of frequencies. To construct a table of frequencies of the relationship between gender and study area for the survey data, and store it as the object tab:
# survey <- read.csv('/course/data/survey.csv', header=TRUE)
# tab <- table(survey$gender, survey$study.area)
Now to construct a clustered bar chart based on this table, including a legend:
# survey <- read.csv('data/survey.csv', header=TRUE)
# tab <- table(survey$gender, survey$study.area)
# barplot(tab, beside=TRUE, legend=TRUE)
You can plot named functions using the plot function, as shown above. There is more versatile function, the curve function, that allows you to also plot functions specified by an expression involving “x”.
An example in which the function is specified by name:
curve(sin, from=0, to=2*pi)
An example in which the function is specified by an expression involving
“x”:
curve(x^2 + 2*x -2, from=-3, to=3)
# The curve function You can plot named functions using the plot
function, as shown above. There is more versatile function, the curve
function, that allows you to also plot functions specified by an
expression involving “x”.
An example in which the function is specified by name:
curve(sin, from=0, to=2*pi)
curve(x^2 + 2*x -2, from=-3, to=3)
There are several options that you can add to most of the high level graphical functions. The main ones are these: - type. The type of graph to create - e.g. p (points), l (lines), b (points and lines). - main. A title for the graph. - sub. A subtitle for the graph. - xlab. A label for the x-axis. - ylab. A label for the y-axis. - xlim. The x-axis limits - a vector of length 2, e.g. c(0, 10). - ylim. The y-axis limits - a vector of length 2, e.g. c(0, 10). - axes. Whether to draw the axes - TRUE or FALSE (defaults to TRUE). Here’s a graph with most of these options set:
plot(
x = 1:10,
y = 10:1,
type = "b",
main = "A customised plot",
sub = "With a sub-heading",
xlab = "Ten random values",
ylab = "Ten more random values",
xlim = c(-2, 12),
ylim = c(-2, 12),
)
# Parameters There are also many graphical parameters that you can
specify, to control the way things appear. There are 73 of them. To see
a complete list:
?par
Here are some of the most useful ones: - adj. Text justification - 0 (left), 0.5 (centre), 1 (right). - bg. Background colour - e.g. “red”, “#A4FF32”, “rgb(255, 200, 150)”. - cex. Magnification factor - e.g. 0.5, 2. - col. Colour - e.g. “red”, “#A4FF32”, “rgb(255, 200, 150)”. - font. Font style - 1 (normal), 2 (bold), 3 (italics), 4 (bold italics) - lty. Line type - “blank”, “solid”, “dashed”, “dotted”, “dotdash”, “longdash”, “twodash”. - lwd. Line width - e.g. 2, 3. - pch. Plotting character - e.g. “@”, or a number 1-25. - ps. Size in points of texts and symbols - e.g. 14.
Some of these parameters can also be targeted to the title, the subtitle, the axis, and the axis labels. So, in addition to cex, col, and font, there are also: - cex.main, cex.sub, cex.axis, cex.lab - col.main, col.sub, col.axis, col.lab - font.main, font.sub, font.axis, font.lab Here’s an example of their use:
plot(
x = 1:10,
y = 10:1,
main = "A demonstration",
cex.main = 3,
font.main = 2,
xlab = "The x-axis",
ylab = "The y-axis",
col.lab = "blue",
type = "b",
col = "red",
lty = "dashed",
lwd = 2,
pch = "&",
)
You can often (but not always) set these parameters by providing them as arguments to the graphical functions (high and low level). When you do, they take effect just for that function call.
Otherwise, you have to set them using the function par. When you use par they take effect for all ensuing graphs that you produce, until they are changed again.
Here’s the example above, using par:
par(
cex.main = 3,
font.main = 2,
col.lab = "blue",
col = "red",
lty = "dashed",
lwd = 2,
pch = "&"
)
plot(
x = 1:10,
y = 10:1,
main = "A demonstration",
xlab = "The x-axis",
ylab = "The y-axis",
type = "b",
)
Before changing graphical parameters using par, it is typically a good
idea to save the old set of values so that you can restore them
later.
old_par <- par()
# Make changes to parameters
# Produce graphs
par(old_par)
## Warning in par(old_par): graphical parameter "cin" cannot be set
## Warning in par(old_par): graphical parameter "cra" cannot be set
## Warning in par(old_par): graphical parameter "csi" cannot be set
## Warning in par(old_par): graphical parameter "cxy" cannot be set
## Warning in par(old_par): graphical parameter "din" cannot be set
## Warning in par(old_par): graphical parameter "page" cannot be set
You can see what the graphical parameters are currently set to by calling par with no arguments:
par()
## $xlog
## [1] FALSE
##
## $ylog
## [1] FALSE
##
## $adj
## [1] 0.5
##
## $ann
## [1] TRUE
##
## $ask
## [1] FALSE
##
## $bg
## [1] "white"
##
## $bty
## [1] "o"
##
## $cex
## [1] 1
##
## $cex.axis
## [1] 1
##
## $cex.lab
## [1] 1
##
## $cex.main
## [1] 1.2
##
## $cex.sub
## [1] 1
##
## $cin
## [1] 0.15 0.20
##
## $col
## [1] "black"
##
## $col.axis
## [1] "black"
##
## $col.lab
## [1] "black"
##
## $col.main
## [1] "black"
##
## $col.sub
## [1] "black"
##
## $cra
## [1] 28.8 38.4
##
## $crt
## [1] 0
##
## $csi
## [1] 0.2
##
## $cxy
## [1] 0.02604167 0.06329114
##
## $din
## [1] 7 5
##
## $err
## [1] 0
##
## $family
## [1] ""
##
## $fg
## [1] "black"
##
## $fig
## [1] 0 1 0 1
##
## $fin
## [1] 7 5
##
## $font
## [1] 1
##
## $font.axis
## [1] 1
##
## $font.lab
## [1] 1
##
## $font.main
## [1] 2
##
## $font.sub
## [1] 1
##
## $lab
## [1] 5 5 7
##
## $las
## [1] 0
##
## $lend
## [1] "round"
##
## $lheight
## [1] 1
##
## $ljoin
## [1] "round"
##
## $lmitre
## [1] 10
##
## $lty
## [1] "solid"
##
## $lwd
## [1] 1
##
## $mai
## [1] 1.02 0.82 0.82 0.42
##
## $mar
## [1] 5.1 4.1 4.1 2.1
##
## $mex
## [1] 1
##
## $mfcol
## [1] 1 1
##
## $mfg
## [1] 1 1 1 1
##
## $mfrow
## [1] 1 1
##
## $mgp
## [1] 3 1 0
##
## $mkh
## [1] 0.001
##
## $new
## [1] FALSE
##
## $oma
## [1] 0 0 0 0
##
## $omd
## [1] 0 1 0 1
##
## $omi
## [1] 0 0 0 0
##
## $page
## [1] TRUE
##
## $pch
## [1] 1
##
## $pin
## [1] 5.76 3.16
##
## $plt
## [1] 0.1171429 0.9400000 0.2040000 0.8360000
##
## $ps
## [1] 12
##
## $pty
## [1] "m"
##
## $smo
## [1] 1
##
## $srt
## [1] 0
##
## $tck
## [1] NA
##
## $tcl
## [1] -0.5
##
## $usr
## [1] 0 1 0 1
##
## $xaxp
## [1] 0 1 5
##
## $xaxs
## [1] "r"
##
## $xaxt
## [1] "s"
##
## $xpd
## [1] FALSE
##
## $yaxp
## [1] 0 1 5
##
## $yaxs
## [1] "r"
##
## $yaxt
## [1] "s"
##
## $ylbias
## [1] 0.2
Here’s a plot to show which symbols correspond to which numerical pch values:
plot(
x = 1:25,
pch = 1:25
)
# Specifying colours When you specify colours you can do so either by
name, e.g. “red”, or by hexadecimal code, e.g. “#FF0000”, or by using
“rgb(255, 0, 0)” .
You can get a list of colour names using the colors function:
colors()
## [1] "white" "aliceblue" "antiquewhite"
## [4] "antiquewhite1" "antiquewhite2" "antiquewhite3"
## [7] "antiquewhite4" "aquamarine" "aquamarine1"
## [10] "aquamarine2" "aquamarine3" "aquamarine4"
## [13] "azure" "azure1" "azure2"
## [16] "azure3" "azure4" "beige"
## [19] "bisque" "bisque1" "bisque2"
## [22] "bisque3" "bisque4" "black"
## [25] "blanchedalmond" "blue" "blue1"
## [28] "blue2" "blue3" "blue4"
## [31] "blueviolet" "brown" "brown1"
## [34] "brown2" "brown3" "brown4"
## [37] "burlywood" "burlywood1" "burlywood2"
## [40] "burlywood3" "burlywood4" "cadetblue"
## [43] "cadetblue1" "cadetblue2" "cadetblue3"
## [46] "cadetblue4" "chartreuse" "chartreuse1"
## [49] "chartreuse2" "chartreuse3" "chartreuse4"
## [52] "chocolate" "chocolate1" "chocolate2"
## [55] "chocolate3" "chocolate4" "coral"
## [58] "coral1" "coral2" "coral3"
## [61] "coral4" "cornflowerblue" "cornsilk"
## [64] "cornsilk1" "cornsilk2" "cornsilk3"
## [67] "cornsilk4" "cyan" "cyan1"
## [70] "cyan2" "cyan3" "cyan4"
## [73] "darkblue" "darkcyan" "darkgoldenrod"
## [76] "darkgoldenrod1" "darkgoldenrod2" "darkgoldenrod3"
## [79] "darkgoldenrod4" "darkgray" "darkgreen"
## [82] "darkgrey" "darkkhaki" "darkmagenta"
## [85] "darkolivegreen" "darkolivegreen1" "darkolivegreen2"
## [88] "darkolivegreen3" "darkolivegreen4" "darkorange"
## [91] "darkorange1" "darkorange2" "darkorange3"
## [94] "darkorange4" "darkorchid" "darkorchid1"
## [97] "darkorchid2" "darkorchid3" "darkorchid4"
## [100] "darkred" "darksalmon" "darkseagreen"
## [103] "darkseagreen1" "darkseagreen2" "darkseagreen3"
## [106] "darkseagreen4" "darkslateblue" "darkslategray"
## [109] "darkslategray1" "darkslategray2" "darkslategray3"
## [112] "darkslategray4" "darkslategrey" "darkturquoise"
## [115] "darkviolet" "deeppink" "deeppink1"
## [118] "deeppink2" "deeppink3" "deeppink4"
## [121] "deepskyblue" "deepskyblue1" "deepskyblue2"
## [124] "deepskyblue3" "deepskyblue4" "dimgray"
## [127] "dimgrey" "dodgerblue" "dodgerblue1"
## [130] "dodgerblue2" "dodgerblue3" "dodgerblue4"
## [133] "firebrick" "firebrick1" "firebrick2"
## [136] "firebrick3" "firebrick4" "floralwhite"
## [139] "forestgreen" "gainsboro" "ghostwhite"
## [142] "gold" "gold1" "gold2"
## [145] "gold3" "gold4" "goldenrod"
## [148] "goldenrod1" "goldenrod2" "goldenrod3"
## [151] "goldenrod4" "gray" "gray0"
## [154] "gray1" "gray2" "gray3"
## [157] "gray4" "gray5" "gray6"
## [160] "gray7" "gray8" "gray9"
## [163] "gray10" "gray11" "gray12"
## [166] "gray13" "gray14" "gray15"
## [169] "gray16" "gray17" "gray18"
## [172] "gray19" "gray20" "gray21"
## [175] "gray22" "gray23" "gray24"
## [178] "gray25" "gray26" "gray27"
## [181] "gray28" "gray29" "gray30"
## [184] "gray31" "gray32" "gray33"
## [187] "gray34" "gray35" "gray36"
## [190] "gray37" "gray38" "gray39"
## [193] "gray40" "gray41" "gray42"
## [196] "gray43" "gray44" "gray45"
## [199] "gray46" "gray47" "gray48"
## [202] "gray49" "gray50" "gray51"
## [205] "gray52" "gray53" "gray54"
## [208] "gray55" "gray56" "gray57"
## [211] "gray58" "gray59" "gray60"
## [214] "gray61" "gray62" "gray63"
## [217] "gray64" "gray65" "gray66"
## [220] "gray67" "gray68" "gray69"
## [223] "gray70" "gray71" "gray72"
## [226] "gray73" "gray74" "gray75"
## [229] "gray76" "gray77" "gray78"
## [232] "gray79" "gray80" "gray81"
## [235] "gray82" "gray83" "gray84"
## [238] "gray85" "gray86" "gray87"
## [241] "gray88" "gray89" "gray90"
## [244] "gray91" "gray92" "gray93"
## [247] "gray94" "gray95" "gray96"
## [250] "gray97" "gray98" "gray99"
## [253] "gray100" "green" "green1"
## [256] "green2" "green3" "green4"
## [259] "greenyellow" "grey" "grey0"
## [262] "grey1" "grey2" "grey3"
## [265] "grey4" "grey5" "grey6"
## [268] "grey7" "grey8" "grey9"
## [271] "grey10" "grey11" "grey12"
## [274] "grey13" "grey14" "grey15"
## [277] "grey16" "grey17" "grey18"
## [280] "grey19" "grey20" "grey21"
## [283] "grey22" "grey23" "grey24"
## [286] "grey25" "grey26" "grey27"
## [289] "grey28" "grey29" "grey30"
## [292] "grey31" "grey32" "grey33"
## [295] "grey34" "grey35" "grey36"
## [298] "grey37" "grey38" "grey39"
## [301] "grey40" "grey41" "grey42"
## [304] "grey43" "grey44" "grey45"
## [307] "grey46" "grey47" "grey48"
## [310] "grey49" "grey50" "grey51"
## [313] "grey52" "grey53" "grey54"
## [316] "grey55" "grey56" "grey57"
## [319] "grey58" "grey59" "grey60"
## [322] "grey61" "grey62" "grey63"
## [325] "grey64" "grey65" "grey66"
## [328] "grey67" "grey68" "grey69"
## [331] "grey70" "grey71" "grey72"
## [334] "grey73" "grey74" "grey75"
## [337] "grey76" "grey77" "grey78"
## [340] "grey79" "grey80" "grey81"
## [343] "grey82" "grey83" "grey84"
## [346] "grey85" "grey86" "grey87"
## [349] "grey88" "grey89" "grey90"
## [352] "grey91" "grey92" "grey93"
## [355] "grey94" "grey95" "grey96"
## [358] "grey97" "grey98" "grey99"
## [361] "grey100" "honeydew" "honeydew1"
## [364] "honeydew2" "honeydew3" "honeydew4"
## [367] "hotpink" "hotpink1" "hotpink2"
## [370] "hotpink3" "hotpink4" "indianred"
## [373] "indianred1" "indianred2" "indianred3"
## [376] "indianred4" "ivory" "ivory1"
## [379] "ivory2" "ivory3" "ivory4"
## [382] "khaki" "khaki1" "khaki2"
## [385] "khaki3" "khaki4" "lavender"
## [388] "lavenderblush" "lavenderblush1" "lavenderblush2"
## [391] "lavenderblush3" "lavenderblush4" "lawngreen"
## [394] "lemonchiffon" "lemonchiffon1" "lemonchiffon2"
## [397] "lemonchiffon3" "lemonchiffon4" "lightblue"
## [400] "lightblue1" "lightblue2" "lightblue3"
## [403] "lightblue4" "lightcoral" "lightcyan"
## [406] "lightcyan1" "lightcyan2" "lightcyan3"
## [409] "lightcyan4" "lightgoldenrod" "lightgoldenrod1"
## [412] "lightgoldenrod2" "lightgoldenrod3" "lightgoldenrod4"
## [415] "lightgoldenrodyellow" "lightgray" "lightgreen"
## [418] "lightgrey" "lightpink" "lightpink1"
## [421] "lightpink2" "lightpink3" "lightpink4"
## [424] "lightsalmon" "lightsalmon1" "lightsalmon2"
## [427] "lightsalmon3" "lightsalmon4" "lightseagreen"
## [430] "lightskyblue" "lightskyblue1" "lightskyblue2"
## [433] "lightskyblue3" "lightskyblue4" "lightslateblue"
## [436] "lightslategray" "lightslategrey" "lightsteelblue"
## [439] "lightsteelblue1" "lightsteelblue2" "lightsteelblue3"
## [442] "lightsteelblue4" "lightyellow" "lightyellow1"
## [445] "lightyellow2" "lightyellow3" "lightyellow4"
## [448] "limegreen" "linen" "magenta"
## [451] "magenta1" "magenta2" "magenta3"
## [454] "magenta4" "maroon" "maroon1"
## [457] "maroon2" "maroon3" "maroon4"
## [460] "mediumaquamarine" "mediumblue" "mediumorchid"
## [463] "mediumorchid1" "mediumorchid2" "mediumorchid3"
## [466] "mediumorchid4" "mediumpurple" "mediumpurple1"
## [469] "mediumpurple2" "mediumpurple3" "mediumpurple4"
## [472] "mediumseagreen" "mediumslateblue" "mediumspringgreen"
## [475] "mediumturquoise" "mediumvioletred" "midnightblue"
## [478] "mintcream" "mistyrose" "mistyrose1"
## [481] "mistyrose2" "mistyrose3" "mistyrose4"
## [484] "moccasin" "navajowhite" "navajowhite1"
## [487] "navajowhite2" "navajowhite3" "navajowhite4"
## [490] "navy" "navyblue" "oldlace"
## [493] "olivedrab" "olivedrab1" "olivedrab2"
## [496] "olivedrab3" "olivedrab4" "orange"
## [499] "orange1" "orange2" "orange3"
## [502] "orange4" "orangered" "orangered1"
## [505] "orangered2" "orangered3" "orangered4"
## [508] "orchid" "orchid1" "orchid2"
## [511] "orchid3" "orchid4" "palegoldenrod"
## [514] "palegreen" "palegreen1" "palegreen2"
## [517] "palegreen3" "palegreen4" "paleturquoise"
## [520] "paleturquoise1" "paleturquoise2" "paleturquoise3"
## [523] "paleturquoise4" "palevioletred" "palevioletred1"
## [526] "palevioletred2" "palevioletred3" "palevioletred4"
## [529] "papayawhip" "peachpuff" "peachpuff1"
## [532] "peachpuff2" "peachpuff3" "peachpuff4"
## [535] "peru" "pink" "pink1"
## [538] "pink2" "pink3" "pink4"
## [541] "plum" "plum1" "plum2"
## [544] "plum3" "plum4" "powderblue"
## [547] "purple" "purple1" "purple2"
## [550] "purple3" "purple4" "red"
## [553] "red1" "red2" "red3"
## [556] "red4" "rosybrown" "rosybrown1"
## [559] "rosybrown2" "rosybrown3" "rosybrown4"
## [562] "royalblue" "royalblue1" "royalblue2"
## [565] "royalblue3" "royalblue4" "saddlebrown"
## [568] "salmon" "salmon1" "salmon2"
## [571] "salmon3" "salmon4" "sandybrown"
## [574] "seagreen" "seagreen1" "seagreen2"
## [577] "seagreen3" "seagreen4" "seashell"
## [580] "seashell1" "seashell2" "seashell3"
## [583] "seashell4" "sienna" "sienna1"
## [586] "sienna2" "sienna3" "sienna4"
## [589] "skyblue" "skyblue1" "skyblue2"
## [592] "skyblue3" "skyblue4" "slateblue"
## [595] "slateblue1" "slateblue2" "slateblue3"
## [598] "slateblue4" "slategray" "slategray1"
## [601] "slategray2" "slategray3" "slategray4"
## [604] "slategrey" "snow" "snow1"
## [607] "snow2" "snow3" "snow4"
## [610] "springgreen" "springgreen1" "springgreen2"
## [613] "springgreen3" "springgreen4" "steelblue"
## [616] "steelblue1" "steelblue2" "steelblue3"
## [619] "steelblue4" "tan" "tan1"
## [622] "tan2" "tan3" "tan4"
## [625] "thistle" "thistle1" "thistle2"
## [628] "thistle3" "thistle4" "tomato"
## [631] "tomato1" "tomato2" "tomato3"
## [634] "tomato4" "turquoise" "turquoise1"
## [637] "turquoise2" "turquoise3" "turquoise4"
## [640] "violet" "violetred" "violetred1"
## [643] "violetred2" "violetred3" "violetred4"
## [646] "wheat" "wheat1" "wheat2"
## [649] "wheat3" "wheat4" "whitesmoke"
## [652] "yellow" "yellow1" "yellow2"
## [655] "yellow3" "yellow4" "yellowgreen"
You can also get a demonstration of the colours:
demo(colors)
##
##
## demo(colors)
## ---- ~~~~~~
##
## > ### ----------- Show (almost) all named colors ---------------------
## >
## > ## 1) with traditional 'graphics' package:
## > showCols1 <- function(bg = "gray", cex = 0.75, srt = 30) {
## + m <- ceiling(sqrt(n <- length(cl <- colors())))
## + length(cl) <- m*m; cm <- matrix(cl, m)
## + ##
## + require("graphics")
## + op <- par(mar=rep(0,4), ann=FALSE, bg = bg); on.exit(par(op))
## + plot(1:m,1:m, type="n", axes=FALSE)
## + text(col(cm), rev(row(cm)), cm, col = cl, cex=cex, srt=srt)
## + }
##
## > showCols1()
##
## > ## 2) with 'grid' package:
## > showCols2 <- function(bg = "grey", cex = 0.75, rot = 30) {
## + m <- ceiling(sqrt(n <- length(cl <- colors())))
## + length(cl) <- m*m; cm <- matrix(cl, m)
## + ##
## + require("grid")
## + grid.newpage(); vp <- viewport(width = .92, height = .92)
## + grid.rect(gp=gpar(fill=bg))
## + grid.text(cm, x = col(cm)/m, y = rev(row(cm))/m, rot = rot,
## + vp=vp, gp=gpar(cex = cex, col = cm))
## + }
##
## > showCols2()
## Loading required package: grid
##
## > showCols2(bg = "gray33")
##
## > ###
## >
## > ##' @title Comparing Colors
## > ##' @param col
## > ##' @param nrow
## > ##' @param ncol
## > ##' @param txt.col
## > ##' @return the grid layout, invisibly
## > ##' @author Marius Hofert, originally
## > plotCol <- function(col, nrow=1, ncol=ceiling(length(col) / nrow),
## + txt.col="black") {
## + stopifnot(nrow >= 1, ncol >= 1)
## + if(length(col) > nrow*ncol)
## + warning("some colors will not be shown")
## + require(grid)
## + grid.newpage()
## + gl <- grid.layout(nrow, ncol)
## + pushViewport(viewport(layout=gl))
## + ic <- 1
## + for(i in 1:nrow) {
## + for(j in 1:ncol) {
## + pushViewport(viewport(layout.pos.row=i, layout.pos.col=j))
## + grid.rect(gp= gpar(fill=col[ic]))
## + grid.text(col[ic], gp=gpar(col=txt.col))
## + upViewport()
## + ic <- ic+1
## + }
## + }
## + upViewport()
## + invisible(gl)
## + }
##
## > ## A Chocolate Bar of colors:
## > plotCol(c("#CC8C3C", paste0("chocolate", 2:4),
## + paste0("darkorange", c("",1:2)), paste0("darkgoldenrod", 1:2),
## + "orange", "orange1", "sandybrown", "tan1", "tan2"),
## + nrow=2)
##
## > ##' Find close R colors() to a given color {original by Marius Hofert)
## > ##' using Euclidean norm in (HSV / RGB / ...) color space
## > nearRcolor <- function(rgb, cSpace = c("hsv", "rgb255", "Luv", "Lab"),
## + dist = switch(cSpace, "hsv" = 0.10, "rgb255" = 30,
## + "Luv" = 15, "Lab" = 12))
## + {
## + if(is.character(rgb)) rgb <- col2rgb(rgb)
## + stopifnot(length(rgb <- as.vector(rgb)) == 3)
## + Rcol <- col2rgb(.cc <- colors())
## + uniqC <- !duplicated(t(Rcol)) # gray9 == grey9 (etc)
## + Rcol <- Rcol[, uniqC] ; .cc <- .cc[uniqC]
## + cSpace <- match.arg(cSpace)
## + convRGB2 <- function(Rgb, to)
## + t(convertColor(t(Rgb), from="sRGB", to=to, scale.in=255))
## + ## the transformation, rgb{0..255} --> cSpace :
## + TransF <- switch(cSpace,
## + "rgb255" = identity,
## + "hsv" = rgb2hsv,
## + "Luv" = function(RGB) convRGB2(RGB, "Luv"),
## + "Lab" = function(RGB) convRGB2(RGB, "Lab"))
## + d <- sqrt(colSums((TransF(Rcol) - as.vector(TransF(rgb)))^2))
## + iS <- sort.list(d[near <- d <= dist])# sorted: closest first
## + setNames(.cc[near][iS], format(zapsmall(d[near][iS]), digits=3))
## + }
##
## > nearRcolor(col2rgb("tan2"), "rgb")
## 0.0 21.1 25.8 29.5
## "tan2" "tan1" "sandybrown" "sienna1"
##
## > nearRcolor(col2rgb("tan2"), "hsv")
## 0.0000 0.0410 0.0618 0.0638 0.0667 0.0766
## "tan2" "sienna2" "coral2" "tomato2" "tan1" "coral"
## 0.0778 0.0900 0.0912 0.0918
## "sienna1" "sandybrown" "coral1" "tomato"
##
## > nearRcolor(col2rgb("tan2"), "Luv")
## 0.00 7.42 7.48 12.41 13.69
## "tan2" "tan1" "sandybrown" "orange3" "orange2"
##
## > nearRcolor(col2rgb("tan2"), "Lab")
## 0.00 5.56 8.08 11.31
## "tan2" "tan1" "sandybrown" "peru"
##
## > nearRcolor("#334455")
## 0.0867
## "darkslategray"
##
## > ## Now, consider choosing a color by looking in the
## > ## neighborhood of one you know :
## >
## > plotCol(nearRcolor("deepskyblue", "rgb", dist=50))
##
## > plotCol(nearRcolor("deepskyblue", dist=.1))
##
## > plotCol(nearRcolor("tomato", "rgb", dist= 50), nrow=3)
##
## > plotCol(nearRcolor("tomato", "hsv", dist=.12), nrow=3)
##
## > plotCol(nearRcolor("tomato", "Luv", dist= 25), nrow=3)
##
## > plotCol(nearRcolor("tomato", "Lab", dist= 18), nrow=3)
# Low level graphical functions Low level graphical functions are what
you can use to add further features to the current plot, such as points,
lines, and text. Again, there are many such functions - here we consider
just some of the most commonly used ones.
You can use the points function to add one or more points. Use the x argument to specify the x-values of the points; use the y argument to specify the y-values.
plot(1:10)
points(
x = c(2, 3),
y = c(9, 9),
)
You can change the shape and colour of the points using the parameters pch and col:
plot(1:10)
points(
x = c(2, 3),
y = c(9, 9),
pch = 8, # 8 is a star
col = 'red',
)
You can use the lines function to add one or more lines according to the coordinates of their starting and ending points. The x argument specifies the x-values of the points to join; the y argument specifies the y-values.
plot(1:10)
lines(
c(2, 3, 4, 5),
c(9, 9, 8, 8),
)
You can change the line type, the line width, and the line colour using
lty, lwd, and col:
plot(1:10)
lines(
x = c(2, 3, 4, 5),
y = c(9, 9, 8, 8),
lty = 5, # 5 is longdash
lwd = 2,
col = 'blue',
)
# The abline function You can use the abline function to add a line with
a given gradient (a) and y-intercept (b):
plot(1:10)
# Add a line with gradient 4, y-intercept 0.5
abline(
a = c(4, 6),
b = c(0.5, -1),
)
# Add a line with gradient 6, y-intercept -1
abline(
a = 6,
b = -1,
)
You can use lty, lwd, and col as for lines:
plot(1:10)
abline(
a = 6,
b = -0.5,
lty = 5,
lwd = 2,
col = 'blue',
)
You can add the horizontal line with equation y = a by using h=a; you can add the vertical line with equation x = a by using v=a:
curve(
x^2 + 2*x -2,
from = -3,
to = 3,
col = 'blue',
lwd = 2,
)
abline(
h = 0,
lty = 3,
)
abline(
v = 0,
lty = 3,
)
# The text function You can use the text function to add items of text.
Use the x argument to specify the x-values of the locations of the
items; use the y argument to specify the y-values of the locations; use
the labels argument to specify the text.
# Plot the sin curve
plot(
sin,
from = 0,
to = 2*pi,
)
# Add points at the max and min
points(
x = c(pi/2, 3*pi/2),
y = c(1, -1),
)
# Add text at the max and min
text(
x = c(pi/2, 3*pi/2),
y = c(1, -1),
labels = c('Max', 'Min'),
)
You can use the pos argument to specify where to place each item of text
in relation to its point: 1 (below), 2 (left), 3 (above), 4 (right).
When you do so, you can use the offset argument to specify how far to
move the text, in fractions of a character width.
You can use the font argument to specify the style of text: 1 (plain), 2 (bold), 3 (italic), 4 (bold italic). You can use the cex argument to specify a factor by which to expand or shrink the text. And you can use the col argument to specify the colour of the text.
# Plot the sin curve
plot(
sin,
from = 0,
to = 2*pi,
)
# Add points at the max and min
points(
x = c(pi/2, 3*pi/2),
y = c(1, -1),
)
# Add text at the max and min
text(
x = c(pi/2, 3*pi/2),
y = c(1, -1),
labels = c('Max', 'Min'),
pos = c(3, 4),
offset = c(0.5, 0.5),
font = c(2, 3),
cex = c(1.5, 1.5),
col = c('green', 'red'),
)
As you have seen, when you call a low level graphical function it adds the result to the current plot, but when you call a high level graphical function it starts a new plot. What if you want it added to the current plot instead? You can get that, by adding the argument add=TRUE.
Default behaviour - new plot created:
plot(sin, from=0, to=2*pi)
plot(cos, from=0, to=2*pi)
Default overridden - added to the current plot:
plot(sin, from=0, to=2*pi)
plot(cos, from=0, to=2*pi, add=TRUE)
What if you want multiple plots together, but on separate axes? You
can get that, by using par and setting the parameter mfrow
or mfcol.
Suppose you want to plot the sin and cos functions, laid out
horizontally on a 2 x 2 grid. First, you use the par
function and set mfrow=c(2, 2). Then you do your plotting
as normal.
par(mfrow = c(2, 2))
plot(sin, from=0, to=2*pi)
plot(cos, from=0, to=2*pi)
What if you want to lay them out vertically instead? Then you’d use
mfcol:
par(mfcol = c(2, 2))
plot(sin, from=0, to=2*pi)
plot(cos, from=0, to=2*pi)
Keep in mind that because you’ve used par the setting will stay in effect until you change it (e.g. set it back to the default of c(1, 1)).